package app

import (
	"context"
	"encoding/json"
	"io/fs"
	"mime"
	"path/filepath"
	"strings"
	"time"
)

type Time time.Time

func (j *Time) UnmarshalJSON(b []byte) error {
	jsonText := string(b)
	s := strings.Trim(jsonText, "\"")
	t, err := time.Parse("2006-01-02 15:04:05", s)
	if err != nil {
		return err
	}
	*j = Time(t)
	return nil
}

type folder struct {
	ID           json.Number `json:"id"`
	ParentID     json.Number `json:"parentId"`
	FileCata     int         `json:"fileCata"`
	FileCount    int         `json:"fileCount"`
	FileListSize int         `json:"fileListSize"`
	LastOpTime   Time        `json:"lastOpTime"`
	CreateDate   Time        `json:"createDate"`
	DirName      string      `json:"name"`
	Rev          string      `json:"rev"`
	StarLabel    int         `json:"starLabel"`
}

func (f *folder) Info() (fs.FileInfo, error) { return f, nil }

func (f *folder) Id() string         { return f.ID.String() }
func (f *folder) PId() string        { return f.ParentID.String() }
func (f *folder) Name() string       { return f.DirName }
func (f *folder) Size() int64        { return 0 }
func (f *folder) Type() fs.FileMode  { return fs.ModeDir }
func (f *folder) Mode() fs.FileMode  { return fs.ModeDir }
func (f *folder) ModTime() time.Time { return time.Time(f.LastOpTime) }
func (f *folder) IsDir() bool        { return true }
func (f *folder) Sys() any           { return nil }

type fileInfo struct {
	ParentID string
	ID       json.Number `json:"id"`

	Md5         string `json:"md5"`
	MediaType   int    `json:"mediaType"`
	FileCata    int    `json:"fileCata"`
	FileName    string `json:"name"`
	FileSize    int64  `json:"size"`
	Orientation int    `json:"orientation"`
	Rev         string `json:"rev"`
	StarLabel   int    `json:"starLabel"`
	LastOpTime  Time   `json:"lastOpTime"`
	CreateDate  Time   `json:"createDate"`
}

func (f *fileInfo) Info() (fs.FileInfo, error) { return f, nil }

func (f *fileInfo) Id() string         { return f.ID.String() }
func (f *fileInfo) PId() string        { return f.ParentID }
func (f *fileInfo) Name() string       { return f.FileName }
func (f *fileInfo) Size() int64        { return f.FileSize }
func (f *fileInfo) Mode() fs.FileMode  { return fs.ModeType }
func (f *fileInfo) Type() fs.FileMode  { return fs.ModeType }
func (f *fileInfo) ModTime() time.Time { return time.Time(f.LastOpTime) }
func (f *fileInfo) IsDir() bool        { return false }
func (f *fileInfo) Sys() any           { return nil }

var builtinTypesLower = map[string]string{
	".mp3":  "audio/ogg",
	".mma":  "audio/ogg",
	".wav":  "audio/wav",
	".flag": "audio/wav",
	".md":   "text/plain",
	".txt":  "text/plain",
	".sh":   "text/plain",
}

// ContentType 自定义解析文件类型, 防止去读取文件来判断是否二进制文件
func (fi *fileInfo) ContentType(ctx context.Context) (string, error) {
	cType := mime.TypeByExtension(filepath.Ext(fi.FileName))
	if cType != "" {
		return cType, nil
	}
	e, ok := builtinTypesLower[strings.ToLower(filepath.Ext(fi.FileName))]
	if ok {
		return e, nil
	}

	return "application/octet-stream", nil
}
